/*
* @Author: dyiwen
* @Date:   2020-09-21 14:14:10
* @Last Modified by:   dyiwen
* @Last Modified time: 2020-09-22 16:28:29
 */
package main

import (
	"encoding/json"
	"fmt"
	"github.com/modood/table"
	"github.com/urfave/cli"
	"os"
	"strings"
	// "github.com/kirinlabs/HttpRequest"
)

func checkerr(err error) {
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

func check_args(c *cli.Context) {
	if c.Args().First() == "" {
		cli.ShowSubcommandHelp(c)
		os.Exit(1)
	}
}

func check_project(c *cli.Context) {
	if c.String("p") == "" {
		cli.ShowSubcommandHelp(c)
		os.Exit(1)
	} else {
		project = c.String("p")
	}
}

func getProjectHandler(c *cli.Context) error {
	err := file_to_struct()
	checkerr(err)
	url_ := fmt.Sprintf("%s/%s/projects", conf.Url, apiprefix)
	req := request(true)
	req.SetBasicAuth(conf.User, conf.Password)
	res, err := req.Get(url_)
	checkerr(err)
	body, err := res.Body()
	checkerr(err)
	err = json.Unmarshal(body, &getprojectbox)
	checkerr(err)
	var array []ProjectTable
	for k, v := range getprojectbox {
		temp := ProjectTable{
			k, v.Name, v.Metadata.Public,
			v.Deleted, v.Owner_name, v.Repo_count,
			v.Chart_count, v.Creation_time,
		}
		array = append(array, temp)
	}
	t := table.Table(array)
	fmt.Println(t)
	return nil
}

func getRepoHandler(c *cli.Context) error {
	err := file_to_struct()
	checkerr(err)
	check_project(c)
	url_ := fmt.Sprintf("%s/%s/projects/%s/repositories", conf.Url, apiprefix, project)
	req := request(true)
	req.SetBasicAuth(conf.User, conf.Password)
	res, err := req.Get(url_, map[string]interface{}{
		"page":      page,
		"page_size": page_size,
	})
	checkerr(err)
	body, err := res.Body()
	checkerr(err)
	err = json.Unmarshal(body, &getrepobox)
	checkerr(err)
	var array []RepoTable
	for k, v := range getrepobox {
		temp := RepoTable{
			k, strings.Replace(v.Name, "common/", "", 1), project, v.Artifact_count, v.Creation_time,
		}
		array = append(array, temp)
	}
	t := table.Table(array)
	fmt.Println(t)
	return nil
}

func getImageHandler(c *cli.Context) error {
	err := file_to_struct()
	checkerr(err)
	check_args(c)
	repo = urlCodeHandler(c.Args().First())
	url_ := fmt.Sprintf("%s/%s/projects/%s/repositories/%s/artifacts", conf.Url, apiprefix, project, repo)
	req := request(true)
	req.SetBasicAuth(conf.User, conf.Password)
	res, err := req.Get(url_)
	checkerr(err)
	body, err := res.Body()
	checkerr(err)
	err = json.Unmarshal(body, &getimagebox)
	checkerr(err)
	var array []ImageTable
	var n int = 1
	for _, v := range getimagebox {
		for _, vv := range v.Tags {
			temp := ImageTable{
				n, fmt.Sprintf("harbor.lingda.com/%s/%s", project, c.Args().First()),
				vv.Name, formatFileSize(v.Size),
				fmt.Sprintf("%s/%s", v.Extra_attrs.Os, v.Extra_attrs.Architecture),
				vv.Push_time,
			}
			array = append(array, temp)
			n = n + 1
		}
	}
	t := table.Table(array)
	fmt.Println(t)
	return nil
}

func searchRepoHandler(c *cli.Context) error {
	err := file_to_struct()
	checkerr(err)
	check_project(c)
	check_args(c)
	url_ := fmt.Sprintf("%s/%s/projects/%s/repositories", conf.Url, apiprefix, project)
	req := request(true)
	req.SetBasicAuth(conf.User, conf.Password)
	res, err := req.Get(url_, map[string]interface{}{
		"q": fmt.Sprintf("name=~%s", c.Args().First()),
	})
	checkerr(err)
	body, err := res.Body()
	checkerr(err)
	if strings.Contains(string(body), "[]") {
		fmt.Printf("%s* is not in this repository\n", c.Args().First())
		os.Exit(1)
	}
	err = json.Unmarshal(body, &getrepobox)
	checkerr(err)
	var array []RepoTable
	for k, v := range getrepobox {
		temp := RepoTable{
			k, strings.Replace(v.Name, "common/", "", 1), project, v.Artifact_count, v.Creation_time,
		}
		array = append(array, temp)
	}
	t := table.Table(array)
	fmt.Println(t)
	return nil
}

func searchImageByTagsHandler(c *cli.Context) error {
	err := file_to_struct()
	checkerr(err)
	check_args(c)
	repo = urlCodeHandler(c.Args().First())
	url_ := fmt.Sprintf("%s/%s/projects/%s/repositories/%s/artifacts", conf.Url, apiprefix, project, repo)
	req := request(true)
	req.SetBasicAuth(conf.User, conf.Password)
	res, err := req.Get(url_, map[string]interface{}{
		"q": fmt.Sprintf("tags=~%s", tags),
	})
	checkerr(err)
	body, err := res.Body()
	checkerr(err)
	err = json.Unmarshal(body, &getimagebox)
	checkerr(err)
	var array []ImageTable
	var n int = 1
	for _, v := range getimagebox {
		for _, vv := range v.Tags {
			temp := ImageTable{
				n, fmt.Sprintf("harbor.lingda.com/%s/%s", project, c.Args().First()),
				vv.Name, formatFileSize(v.Size),
				fmt.Sprintf("%s/%s", v.Extra_attrs.Os, v.Extra_attrs.Architecture),
				vv.Push_time,
			}
			array = append(array, temp)
			n = n + 1
		}
	}
	t := table.Table(array)
	fmt.Println(t)
	return nil
}

func loginHandler(c *cli.Context) error {
	check_args(c)
	fmt.Printf("Username:")
	fmt.Scanln(&user)
	fmt.Printf("Password:")
	fmt.Scanln(&password)
	main_url = c.Args().First()
	if !strings.Contains(main_url, "https") {
		main_url = "https://" + main_url
	} else if !strings.Contains(main_url, "http") {
		main_url = "https://" + main_url
	}
	req := request(true)
	req.SetBasicAuth(user, password)
	res, err := req.Get(main_url + apiprefix + loginprefix)
	checkerr(err)
	if res.StatusCode() == 200 {
		fmt.Printf("Login Succeeded! %s\n", main_url)
		conf = Config{
			Url:      main_url,
			User:     user,
			Password: password,
		}
		err = write_to_config(conf)
		checkerr(err)
	} else {
		fmt.Printf("Login Failed! %s for user '%s'", main_url, user)
	}
	return nil
}

func logoutHandler(c *cli.Context) error {
	if strings.Contains(homedir, "/.harborctl/") {
		err := RemoveAll(homedir)
		checkerr(err)
		fmt.Println("Logout Success!")
	} else {
		fmt.Println("无法安全退出！")
	}
	return nil
}

func checkHandler(c *cli.Context) error {
	err := file_to_struct()
	checkerr(err)
	fmt.Printf("Cureent User: %s \n", conf.User)
	fmt.Printf("Cureent WebSite: %s \n", conf.Url)
	return nil
}
